package cn.learn.jdk8new.lambda;

import cn.learn.jdk8new.Employee;
import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.*;

/**
 * 学习lambda表达式的  方法引用、构造器引用
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2020年03月23日20:03
 */
public class LearnLambda2 {

    /*
     * 一、方法引用：若Lambda体中的内容有方法已经实现了，我们可以使用“方法引用”
     *          （可以理解为方法引用是Lambda表达式的另外一种形式）
     *
     * 只要有三种语法格式：
     *      对象::实例方法名
     *      类::静态方法名
     *      类::实例方法名
     *
     * 注意：
     *  ①Lambda 体中调用方法的参数列表与返回值类型，要与函数式接口中抽象方法的函数列表和返回值保持一致！
     *  ②如Lambda 参数列表的第一个参数是实例方法的调用者，而第二个参数是实例方法的参数时，可以使用 ClassName::method
     *
     * 二、构造器引用
     * 格式：
     *      ClassName::new
     * 注意：需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致！
     *
     * 三、数组引用
     *      type[]::new
     */

    /**
     * 对象::实例方法名
     * 如：System.out.println("--------");
     */
    @Test
    public void test1() {
        Consumer<String> conn1 = x -> System.out.println(x);
        conn1.accept("第一个例子");

        PrintStream      ps    = System.out;
        Consumer<String> conn2 = ps::println;
        conn2.accept("第二个例子");

        Consumer<String> conn3 = System.out::println;
        conn3.accept("第三个例子");
    }

    /**
     * 对象::实例方法名
     */
    @Test
    public void test2() {
        Employee employee = new Employee();
        employee.setName("张三");
        employee.setAge(12);

        Supplier<String> supplier1 = () -> employee.getName();
        String           name      = supplier1.get();
        System.out.println(name);

        Supplier<Integer> supplier2 = employee::getAge;
        Integer           age       = supplier2.get();
        System.out.println(age);
    }

    /**
     * 类::静态方法名
     */
    @Test
    public void test3() {
        Comparator<Integer> comparator1 = (x, y) -> Integer.compare(x, y);

        Comparator<Integer> comparator2 = Integer::compare;
    }

    /**
     * 类::实例方法名
     */
    @Test
    public void test4() {
        BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);

        BiPredicate<String, String> bp2 = String::equals;
    }

    /**
     * 构造器引用
     */
    @Test
    public void test5() {
        Supplier<Employee> supplier1 = () -> new Employee();

        //构造器引用（无参）
        Supplier<Employee> supplier2 = Employee::new;
    }

    @Test
    public void test6() {
        //一个参数构造器
        Function<Integer, Employee> fun1 = (x) -> new Employee(x);

        Function<Integer, Employee> fun2 = Employee::new;
        Employee employee1 = fun2.apply(28);
        System.out.println(employee1);

        //两个参数的构造器
        BiFunction<Integer, String, Employee> bf = Employee::new;
        Employee employee2 = bf.apply(17, "王五");
        System.out.println(employee2);
    }

    @Test
    public void test7(){
        Function<Integer,String[]> fun1 = (x) -> new String[x];
        String[] apply = fun1.apply(10);
        System.out.println(apply.length);

        Function<Integer,String[]> fun2 = String[]::new;
        String[]                   apply1 = fun2.apply(20);
        System.out.println(apply1.length);
    }


}
